package com.sy.simpleegg.platform.lyybox

import android.util.Log
import com.sy.simpleegg.ext.logFile
import com.sy.simpleegg.serialport.base.BaseController
import com.sy.simpleegg.serialport.bean.ComData
import com.sy.simpleegg.serialport.util.ConvertHex
import com.sy.simpleegg.util.ByteUtil
import org.cnbleu.serialport.SerialPort
import java.text.SimpleDateFormat
import java.util.Date


abstract class LyyBoxBaseController(
    portName: String,
    baudrate: SerialPort.BAUDRATE,
    stopb: SerialPort.STOPB,
    datab: SerialPort.DATAB,
    parity: SerialPort.PARITY,
    speed: Long
) : BaseController(portName, baudrate, stopb, datab, parity, speed) {

    private val TAG = javaClass.simpleName

    private val HEAD = byteArrayOf(0xAA.toByte())
    private val END = byteArrayOf(0xDD.toByte())

    private var ADD_CODE: Int = 26

    /**
     * 查询链接状态
     */
    private val CMD_CHECK_CONNECT = "01"

    /**
     * 线上支付-云上分
     */
    private val CMD_CLOUD = "03"

    /**
     * 线上支付（新）-状态
     */
    private val CMD_STATE = "D1"

    /**
     * 线上支付（新）-主板状态查询
     */
    private val CMD_STATE_SUB_STATE = "01"

    /**
     * 线上支付（新）-自定义套餐云上分
     */
    private val CMD_STATE_SUB_CLOUD = "02"

    /**
     * 线上支付（新）-出币结果上报盒子后，响应控制板的数据
     */
    private val CMD_STATE_SUB_OUT_RESULT = "03"

    /**
     * 查询终端参数
     */
    private val CMD_GET_TERMINAL_CONFIG = "05"

    /**
     * 设置终端参数
     */
    private val CMD_SET_TERMINAL_CONFIG = "15"

    /**
     * 响应控制板获取支付二维码，下发支付二维码数据
     */
    private val CMD_PAY_QR_CODE = "10"

    /**
     * 响应终端主动上传账目增量
     */
    private val CMD_REC_OUT_COUNT_ADD_LIST = "14"

    /**
     * 下发盒子网络状态
     */
    private val CMD_BOX_NETWORK = "19"

    /**
     * 下发扩展参数
     */
    private val CMD_EXT = "xx"

    init {

    }

    /**
     * 响应盒子查询链接状态
     * @param loginFlag 登录标识
     */
    fun respCheckConnect(loginFlag: Int) {
        try {
            val loginFlagHex = ByteUtil.int2HexStr(loginFlag, 4, true)
            val loginFlagBytes = ByteUtil.hexStr2bytes(loginFlagHex!!)
            val preBytes = byteArrayOf(0x05, 0x02, 0x01)
            val checkDataBytes = ByteUtil.combineByteArray(preBytes, loginFlagBytes)
            val checkBytes = byteArrayOf(ByteUtil.getXor(checkDataBytes))
            val result = ByteUtil.combineByteArray(
                ByteUtil.combineByteArray(
                    ByteUtil.combineByteArray(
                        HEAD,
                        checkDataBytes
                    ), checkBytes
                ), END
            )
            sendBytes(result)
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("响应盒子查询链接状态异常：${e.message}")
        }
    }

    /**
     * 响应线上支付-云上分
     * @param result 0-失败 1-成功
     */
    fun respCloud(success: Int) {
        try {
            val successHex = ByteUtil.int2HexStr(success, 2, true)
            val successBytes = ByteUtil.hexStr2bytes(successHex!!)
            val preBytes = byteArrayOf(0x04, 0x02, 0x03)
            val checkDataBytes = ByteUtil.combineByteArray(preBytes, successBytes)
            val checkBytes = byteArrayOf(ByteUtil.getXor(checkDataBytes))
            val result = ByteUtil.combineByteArray(
                ByteUtil.combineByteArray(
                    ByteUtil.combineByteArray(
                        HEAD,
                        checkDataBytes
                    ), checkBytes
                ), END
            )
            sendBytes(result)
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("响应线上支付-云上分异常：${e.message}")
        }
    }

    /**
     * 响应主板状态查询
     * @param unicode 唯一码，返回与下发一致
     * @param state 0-离线 1-待支付状态
     */
    fun respCheckState(unicode: String, state: Int) {
        try {
            val unicodeHex = ByteUtil.str2HexStr(unicode, 12)
            val stateHex = ByteUtil.int2HexStr(state, 2, true)
            val unicodeBytes = ByteUtil.hexStr2bytes(unicodeHex!!)
            val stateBytes = ByteUtil.hexStr2bytes(stateHex!!)

            val preBytes = byteArrayOf(0x0B, 0x02, 0xD1.toByte(), 0x01)
            val checkDataBytes = ByteUtil.combineByteArray(
                preBytes,
                ByteUtil.combineByteArray(unicodeBytes, stateBytes)
            )
            val checkBytes = byteArrayOf(ByteUtil.getXor(checkDataBytes))
            val result = ByteUtil.combineByteArray(
                ByteUtil.combineByteArray(
                    ByteUtil.combineByteArray(
                        HEAD,
                        checkDataBytes
                    ), checkBytes
                ), END
            )
            sendBytes(result)
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("响应主板状态查询异常：${e.message}")
        }
    }

    /**
     * 响应主板自定义云上分结果
     * @param unicode 唯一码，返回与下发一致
     * @param payAmount 金额
     * @param resultCode 上分结果 0-启动失败 1-启动正常 2-正在启动 3-其他故障
     * @param coins 上分数（仅供参考） 实际上报报币数使用0x14指令
     */
    fun respCloudNew(unicode: String, payAmount: Int, resultCode: Int, coins: Int) {
        try {
            val unicodeHex = ByteUtil.str2HexStr(unicode, 12)
            val payAmountHex = ByteUtil.int2HexStr(payAmount, 4, true)
            val resultCodeHex = ByteUtil.int2HexStr(resultCode, 2, true)
            val coinsHex = ByteUtil.int2HexStr(coins, 2, true)
            val dataBytes =
                ByteUtil.hexStr2bytes(unicodeHex + payAmountHex + resultCodeHex + coinsHex)

            val preBytes = byteArrayOf(0x0F, 0x02, 0xD1.toByte(), 0x02)
            val checkDataBytes = ByteUtil.combineByteArray(preBytes, dataBytes)
            val checkBytes = byteArrayOf(ByteUtil.getXor(checkDataBytes))
            val result = ByteUtil.combineByteArray(
                ByteUtil.combineByteArray(
                    ByteUtil.combineByteArray(
                        HEAD,
                        checkDataBytes
                    ), checkBytes
                ), END
            )
            sendBytes(result)
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("响应主板自定义云上分结果异常：${e.message}")
        }
    }

    /**
     * 响应主板自定义云上分结果
     * @param unicode 唯一码，返回与下发一致
     * @param payAmount 金额
     * @param resultCode 上分结果 0-启动失败 1-启动正常 2-正在启动 3-其他故障
     * @param coins 上分数（仅供参考） 实际上报报币数使用0x14指令
     */
    fun respOutCoinResult(unicode: String, payAmount: Int, resultCode: Int, coins: Int) {
        try {
            val unicodeHex = ByteUtil.str2HexStr(unicode, 12)
            val payAmountHex = ByteUtil.int2HexStr(payAmount, 4, true)
            val resultCodeHex = ByteUtil.int2HexStr(resultCode, 2, true)
            val coinsHex = ByteUtil.int2HexStr(coins, 2, true)
            val dataBytes =
                ByteUtil.hexStr2bytes(unicodeHex + payAmountHex + resultCodeHex + coinsHex)

            val preBytes = byteArrayOf(0x0F, 0x02, 0xD1.toByte(), 0x03)
            val checkDataBytes = ByteUtil.combineByteArray(preBytes, dataBytes)
            val checkBytes = byteArrayOf(ByteUtil.getXor(checkDataBytes))
            val result = ByteUtil.combineByteArray(
                ByteUtil.combineByteArray(
                    ByteUtil.combineByteArray(
                        HEAD,
                        checkDataBytes
                    ), checkBytes
                ), END
            )
            sendBytes(result)
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("响应主板自定义云上分结果异常：${e.message}")
        }
    }

    fun respTerminalConfig() {
        //TODO
    }

    /**
     * 获取标准二维码
     */
    fun getQrCode() {
        try {
            val checkDataBytes = byteArrayOf(0x03, 0x02, 0x10)
            val checkBytes = byteArrayOf(ByteUtil.getXor(checkDataBytes))
            val result = ByteUtil.combineByteArray(
                ByteUtil.combineByteArray(
                    ByteUtil.combineByteArray(
                        HEAD,
                        checkDataBytes
                    ), checkBytes
                ), END
            )
            sendBytes(result)
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("获取标准二维码异常：${e.message}")
        }
    }

    /**
     * 获取公众号带参二维码
     */
    fun getPublicQrCode() {
        try {
            val checkDataBytes = byteArrayOf(0x04, 0x02, 0xD3.toByte(), 0x02)
            val checkBytes = byteArrayOf(ByteUtil.getXor(checkDataBytes))
            val result = ByteUtil.combineByteArray(
                ByteUtil.combineByteArray(
                    ByteUtil.combineByteArray(
                        HEAD,
                        checkDataBytes
                    ), checkBytes
                ), END
            )
            sendBytes(result)
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("获取公众号带参二维码异常：${e.message}")
        }
    }

    /**
     * 控制板->盒子 上报账目增量
     * @param addCode 自增码
     * @param errCode 故障码
     * @param money 金额
     * @param coins 出币数
     */
    fun uploadCoinListAdd(addCode: String, errCode: String, money: String, coins: String) {
        try {
            var addCodeHex = "1A"
            if (addCode == "-1") {
                addCodeHex = ByteUtil.int2HexStr(ADD_CODE, 2, true)!!
            } else {
                addCodeHex = ByteUtil.int2HexStr(addCode.toInt(), 2, true)!!
            }
            val errCodeHex = ByteUtil.int2HexStr(errCode.toInt(), 2, true)
            val moneyHex = ByteUtil.int2HexStr(money.toInt(), 2, true)
            val coinsHex = ByteUtil.int2HexStr(coins.toInt(), 2, true)

            val preBytes = byteArrayOf(0x0F, 0x02, 0x14)
            val dataHex = addCodeHex + errCodeHex + moneyHex + coinsHex
            val dataBytes = ByteUtil.hexStr2bytes(dataHex)
            val checkDataBytes = ByteUtil.combineByteArray(preBytes, dataBytes)
            val checkBytes = byteArrayOf(ByteUtil.getXor(checkDataBytes))
            val result = ByteUtil.combineByteArray(
                ByteUtil.combineByteArray(
                    ByteUtil.combineByteArray(
                        HEAD,
                        checkDataBytes
                    ), checkBytes
                ), END
            )
            sendBytes(result)
            if (ADD_CODE >= 255) {
                ADD_CODE = 0
            } else {
                ADD_CODE += 1
            }
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("控制板->盒子 上报账目增量 异常：${e.message}")
        }
    }

    /**
     * 查询盒子网络
     */
    fun getBoxNetwork() {
        try {
            val checkDataBytes = byteArrayOf(0x03, 0x02, 0x19)
            val checkBytes = byteArrayOf(ByteUtil.getXor(checkDataBytes))
            val result = ByteUtil.combineByteArray(
                ByteUtil.combineByteArray(
                    ByteUtil.combineByteArray(
                        HEAD,
                        checkDataBytes
                    ), checkBytes
                ), END
            )
            sendBytes(result)
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("查询盒子网络 异常：${e.message}")
        }
    }

    /**
     * 响应盒子的扩展指令
     */
    fun respExt() {
        //TODO
    }

    /**
     * 发送数据
     */
    private fun sendBytes(dataBytes: ByteArray) {
        try {
            log("lyy 发送数据到 支付盒子：" + ByteUtil.bytes2HexStr(dataBytes))
            sendData(dataBytes, 500)
        } catch (e: Exception) {
            e.printStackTrace()
            log("lyy 发送数据到 支付盒子异常：" + e.message)
        }
    }

    override fun onDataReceived(comData: ComData) {
        try {
            val dataHex = ConvertHex.byte2hex(comData.data)
            val head = dataHex.substring(0, 2)
            val end = dataHex.substring(dataHex.length - 2)
            log("收到 lyy盒子 数据：$dataHex")
            if (head == "AA" && end == "DD") {
                val len = dataHex.substring(2, 4).toInt(16)
                val indexHex = dataHex.substring(4, 6)
                when (indexHex) {
                    "01" -> {
                        //盒子标识，处理盒子下发的数据
                        when (dataHex.substring(6, 8)) {
                            CMD_CHECK_CONNECT -> {
                                pushCheckConnect(dataHex)
                            }

                            CMD_CLOUD -> {
                                pushCloud(dataHex)
                            }

                            CMD_STATE -> {
                                when (val subCmd = dataHex.substring(8, 10)) {
                                    CMD_STATE_SUB_STATE -> {
                                        pushCheckState(dataHex)
                                    }

                                    CMD_STATE_SUB_CLOUD -> {
                                        pushCloudNew(dataHex)
                                    }

                                    CMD_STATE_SUB_OUT_RESULT -> {
                                        pushOutResultResp(dataHex)
                                    }

                                    else -> log("未定义的 状态子命令 $subCmd")
                                }
                            }

                            CMD_GET_TERMINAL_CONFIG -> {
                                pushGetTerminalConfig(dataHex)
                            }

                            CMD_SET_TERMINAL_CONFIG -> {
                                pushSetTerminalConfig(dataHex)
                            }

                            CMD_PAY_QR_CODE -> {
                                pushPayQrCodeResp(dataHex)
                            }

                            CMD_REC_OUT_COUNT_ADD_LIST -> {
                                pushOutCountListResp(dataHex)
                            }

                            CMD_BOX_NETWORK -> {
                                pushBoxNetworkResp(dataHex)
                            }

                            CMD_EXT -> {
//                                recExtData(dataHex)
                            }
                        }
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            log("lyy控制板 处理响应数据异常：" + e.message)
        }
    }

    /**
     * 盒子-->链接控制板 查询连接状态
     */
    abstract fun pushCheckConnect(dataHex: String)

    /**
     * 盒子-->云上分
     */
    abstract fun pushCloud(dataHex: String)

    /**
     * 盒子-->控制板状态查询
     */
    abstract fun pushCheckState(dataHex: String)

    /**
     * 盒子-->云上分（新）
     */
    abstract fun pushCloudNew(dataHex: String)

    /**
     * 盒子-->出币结果上报的响应
     */
    abstract fun pushOutResultResp(dataHex: String)

    /**
     * 盒子-->获取终端参数
     */
    abstract fun pushGetTerminalConfig(dataHex: String)

    /**
     * 盒子-->设置终端参数
     */
    abstract fun pushSetTerminalConfig(dataHex: String)

    /**
     * 盒子-->下发支付二维码
     */
    abstract fun pushPayQrCodeResp(dataHex: String)

    /**
     * 盒子-->上传账目增量的响应
     */
    abstract fun pushOutCountListResp(dataHex: String)

    /**
     * 盒子-->盒子网络状态下发
     */
    abstract fun pushBoxNetworkResp(dataHex: String)

    /**
     * 生成一个六位不重复的字符
     */
    private fun unRepeatSixCode(): String? {
        var sixChar = ""
        val sdf = SimpleDateFormat("yyMMddHHmmss")
        val date = Date()
        val time = sdf.format(date)
        for (i in 0 until time.length / 2) {
            var singleChar: String
            val x = time.substring(i * 2, (i + 1) * 2)
            val b = x.toInt()
            singleChar = if (b < 10) {
                Integer.toHexString(x.toInt())
            } else if (b >= 10 && b < 36) {
                (x.toInt() + 55).toChar().toString()
            } else {
                (x.toInt() + 61).toChar().toString()
            }
            sixChar = sixChar + singleChar
        }
        Log.d(TAG, "生成一个6位不可重复的字符编码是：$sixChar")
        return sixChar
    }

    private fun log(msg: String) {
        logFile(msg)
    }

}